﻿#include <QUuid>
#include <QDateTime>
#include <QDebug>
#include "prj_manager_task_widget.h"
#include "ui_prj_manager_task_widget.h"
#include "global_manager.h"
#include "prj_task_edit_dialog.h"
#include "task_info_table.h"
#include "easylogging++.h"

PrjManagerTaskWidget::PrjManagerTaskWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::PrjManagerTaskWidget),
    m_prjUuid(QString()),
    m_sqlOperator(new SqliteManager),
    m_treeWidgetMenu(nullptr),
    m_currentMenuAtItem(nullptr)
{
    ui->setupUi(this);
    initUi();
    initMenu();
    initEvents();
}

PrjManagerTaskWidget::~PrjManagerTaskWidget()
{
    delete ui;
}

void PrjManagerTaskWidget::setPrjUuid(QString uuid)
{
    if (uuid == m_prjUuid)
    {
        return ;
    }

    m_prjUuid = uuid;
    initPrjTaskData();
}

void PrjManagerTaskWidget::setTaskSelectMode()
{
    setWindowTitle(QStringLiteral("选择任务"));
    ui->dialogToolBoxFrame->show();
    ui->taskDetailWidget->hide();
}

QHash<QString, QString> PrjManagerTaskWidget::getCheckedChildren(const QTreeWidgetItem *parent)
{
    QHash<QString, QString> checkedItems;
    for (int i = 0; i < parent->childCount(); i++) {
        QTreeWidgetItem *item = parent->child(i);
        if (item->checkState(0) == Qt::Checked) {
            checkedItems[item->data(0, Qt::UserRole).toString()] = item->text(0);
        } else {
            QHash<QString, QString> checkedChildren = getCheckedChildren(item);
            for (auto it = checkedChildren.begin(); it != checkedChildren.end(); ++it) {
                checkedItems.insert(it.key(), it.value());
            }
        }
    }

    return checkedItems;
}

QHash<QString, QString> PrjManagerTaskWidget::getCheckedTasks()
{
    int rootItemCount = ui->treeWidget->topLevelItemCount();
    LOG(DEBUG) << "root item count: " << rootItemCount;
    QHash<QString, QString> checkedItems;
    for (int i = 0; i < rootItemCount; i++)
    {
        QTreeWidgetItem *root = ui->treeWidget->topLevelItem(i);
        if (root->checkState(0) == Qt::Checked) {
            checkedItems[root->data(0, Qt::UserRole).toString()] = root->text(0);
        }
        else {
            QHash<QString, QString> checkedChildren = getCheckedChildren(root);
            for (auto it = checkedChildren.begin(); it != checkedChildren.end(); ++it) {
                checkedItems.insert(it.key(), it.value());
            }
        }
    }

    return checkedItems;
}

void PrjManagerTaskWidget::initUi()
{
    setAttribute(Qt::WA_StyledBackground);
    ui->treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch);
    ui->treeWidget->setDragEnabled(true);
    ui->treeWidget->setAcceptDrops(true);
    ui->dialogToolBoxFrame->hide();
}

void PrjManagerTaskWidget::initEvents()
{
    connect(ui->newTaskBtn, &QPushButton::clicked, this, &PrjManagerTaskWidget::onNewTaskBtnClicked);
    connect(ui->treeWidget, &QTreeWidget::itemPressed, this,
            [=](QTreeWidgetItem* item, int column) {
        Q_UNUSED(column)
        m_currentMenuAtItem = item;
        if (qApp->mouseButtons() != Qt::RightButton)
        {
            ui->taskDetailWidget->setTaskUuid(item->data(0, Qt::UserRole).toString());
            return ;
        }

        m_treeWidgetMenu->exec(QCursor::pos());
    });

    connect(ui->treeWidget, &TreeWidget::itemIsMoved, this, [=](QTreeWidgetItem *item) {
        QString parentUuid = "";
        QTreeWidgetItem *parentItem = item->parent();

        if (nullptr != parentItem) {
            parentUuid = parentItem->data(0, Qt::UserRole).toString();
        }

        TaskInfoTable tit;
        tit.updateTaskParentUuid(item->data(0, Qt::UserRole).toString(), parentUuid);
    });

    connect(ui->okBtn, &QPushButton::clicked, this, [=]() {
        emit(accept());
    });

    connect(ui->cancelBtn, &QPushButton::clicked, this, [=]() {
        emit(reject());
    });
}

void PrjManagerTaskWidget::initPrjTaskData()
{
    ui->treeWidget->clear();

    QList<QString> fields;
    fields << "uuid" << "parent_task_uuid" << "task_name" << "task_description";
    QHash<QString, QVariant> whereConditions;
    whereConditions["prj_uuid"] = m_prjUuid;
    QList<QVariantList> data;
    bool ret = m_sqlOperator->selectData(TASK_INFO_TABLE_NAME, fields, whereConditions, data);
    if (!ret)
    {
        LOG(ERROR) << "init prj task data failed, error info: "
                   << m_sqlOperator->lastError().toStdString();
        return ;
    }

    QString firstTaskUuid = "";             // 默认展示的任务UUID

    QHash<QString, QTreeWidgetItem*> itemMap;
    for (int i = 0; i < data.count(); i++)
    {
        QString uuid = data[i][0].toString();               // 任务UUID
        QString parentTaskUuid = data[i][1].toString();     // 父任务UUID
        QTreeWidgetItem* newItem = nullptr;                 // 初始化新任务条目为空
        if (itemMap.find(uuid) != itemMap.end())            // 已经存在当前任务节点
        {
            newItem = itemMap[uuid];
            newItem->setText(0, data[i][2].toString());
            newItem->setText(1, data[i][3].toString());
        }
        else                                                // 不存在当前任务节点
        {
            newItem = new QTreeWidgetItem({data[i][2].toString(),
                                           data[i][3].toString()});
            newItem->setData(0, Qt::UserRole, uuid);
            itemMap[uuid] = newItem;
        }

        if (0 == parentTaskUuid.size())                             // 当前任务没有父任务
        {
            if (firstTaskUuid.isEmpty())
            {
                firstTaskUuid = newItem->data(0, Qt::UserRole).toString();
            }
            ui->treeWidget->addTopLevelItem(newItem);
        }
        else if (itemMap.find(parentTaskUuid) != itemMap.end())     // 当前任务的父任务已经存在节点
        {
            QTreeWidgetItem* parentItem = itemMap[parentTaskUuid];
            parentItem->addChild(newItem);
        }
        else                                                        // 当前任务的父任务还没有创建节点
        {
            QTreeWidgetItem* parentItem = new QTreeWidgetItem();
            parentItem->setData(0, Qt::UserRole, parentTaskUuid);
            parentItem->addChild(newItem);
            itemMap[parentTaskUuid] = parentItem;
        }
    }

    LOG(DEBUG) << "set uuid: " << firstTaskUuid.toStdString();
    ui->taskDetailWidget->setTaskUuid(firstTaskUuid);
}

void PrjManagerTaskWidget::initMenu()
{
    if (!m_treeWidgetMenu)
    {
        m_treeWidgetMenu = new QMenu(this);
        QAction *newChildTaskAction = new QAction(QStringLiteral("新建子任务"));
        QAction *editTaskAction = new QAction(QStringLiteral("编辑任务"));
        QAction *deleteTaskAction = new QAction(QStringLiteral("删除任务"));
        QAction *deleteChildTaskAction = new QAction(QStringLiteral("删除子任务"));

        m_treeWidgetMenu->addAction(newChildTaskAction);
        m_treeWidgetMenu->addAction(editTaskAction);
        m_treeWidgetMenu->addAction(deleteTaskAction);
        m_treeWidgetMenu->addAction(deleteChildTaskAction);

        connect(newChildTaskAction, &QAction::triggered, this, &PrjManagerTaskWidget::onNewChildTaskActionTriggered);
        connect(editTaskAction, &QAction::triggered, this, &PrjManagerTaskWidget::onEditTaskActionTriggered);
        connect(deleteTaskAction, &QAction::triggered, this, &PrjManagerTaskWidget::onDeleteTaskActionTriggered);
        connect(deleteChildTaskAction, &QAction::triggered, this, &PrjManagerTaskWidget::onDeleteChildTaskActionTriggered);
    }
}

bool PrjManagerTaskWidget::insertNewTask(QString uuid,
                                    QString prjUuid,
                                    QString parentTaskUuid,
                                    QString taskName,
                                    QString taskDescription,
                                    QString createTime,
                                    QString lastModifyTime,
                                    QString taskStatus)
{
    QList<QString> fields;
    fields << "uuid"
           << "prj_uuid"
           << "parent_task_uuid"
           << "task_name"
           << "task_description"
           << "create_time"
           << "last_modify_time"
           << "task_status";
    QVariantList data;
    data << uuid
         << prjUuid
         << parentTaskUuid
         << taskName
         << taskDescription
         << createTime
         << lastModifyTime
         << taskStatus;
    bool ret = m_sqlOperator->insertRowData(TASK_INFO_TABLE_NAME, fields, data);
    if (!ret)
    {
        LOG(ERROR) << "insert row data failed, error info: "
                   << m_sqlOperator->lastError().toStdString();
    }

    return ret;
}

bool PrjManagerTaskWidget::updateTask(QString uuid,
                                 QString parentTaskUuid,
                                 QString taskName,
                                 QString taskDescription,
                                 QString lastModifyTime,
                                 QString taskStatus)
{
    QHash<QString, QVariant> data;
    data["parent_task_uuid"] = parentTaskUuid;
    data["task_name"] = taskName;
    data["task_description"] = taskDescription;
    data["last_modify_time"] = lastModifyTime;
    data["task_status"] = taskStatus;

    QHash<QString, QVariant> whereConditions;
    whereConditions["uuid"] = uuid;
    bool ret = m_sqlOperator->updateData(TASK_INFO_TABLE_NAME, data, whereConditions);
    if (!ret)
    {
        LOG(ERROR) << "update row data failed, error info: "
                   << m_sqlOperator->lastError().toStdString();
    }

    return ret;
}

bool PrjManagerTaskWidget::deleteTask(QString uuid)
{
    QHash<QString, QVariant> whereConditions;
    whereConditions["uuid"] = uuid;
    int ret = m_sqlOperator->deleteData(TASK_INFO_TABLE_NAME, whereConditions);
    if (!ret)
    {
        LOG(ERROR) << "delete task failed, error info: "
                   << m_sqlOperator->lastError().toStdString();
    }
    return ret;
}

bool PrjManagerTaskWidget::deleteChildTask(QString parentUuid)
{
    QHash<QString, QVariant> whereConditions;
    whereConditions["parent_task_uuid"] = parentUuid;
    int ret = m_sqlOperator->deleteData(TASK_INFO_TABLE_NAME, whereConditions);
    if (!ret)
    {
        LOG(ERROR) << "delete child task failed, error info: "
                   << m_sqlOperator->lastError().toStdString();
    }
    return ret;
}

void PrjManagerTaskWidget::deleteTreeWidgetItem(QTreeWidgetItem *item)
{
    int ret = deleteTask(item->data(0, Qt::UserRole).toString());
    if (!ret)
    {
        return ;
    }

    for (int i = item->childCount() - 1; i >= 0; i--)
    {
        QTreeWidgetItem* childItem = item->child(i);
        deleteTreeWidgetItem(childItem);
        item->removeChild(childItem);
    }
}

void PrjManagerTaskWidget::setDialogMode(bool isDialogMode)
{
    Q_UNUSED(isDialogMode)
}

void PrjManagerTaskWidget::onNewTaskBtnClicked()
{
    PrjTaskEditDialog editDialog(this);
    if (editDialog.exec())
    {
        QString uuid = QUuid::createUuid().toString(QUuid::WithoutBraces);
        QString taskName = editDialog.getTaskName();
        QString taskDescription = editDialog.getTaskDescription();
        QString currentTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        bool ret = insertNewTask(uuid,
                                 m_prjUuid,
                                 "",
                                 taskName,
                                 taskDescription,
                                 currentTime,
                                 currentTime,
                                 0);

        if (!ret)
        {
            return ;
        }

        QTreeWidgetItem* newItem = new QTreeWidgetItem({taskName, taskDescription});
        newItem->setData(0, Qt::UserRole, uuid);
        ui->treeWidget->addTopLevelItem(newItem);
    }
}

void PrjManagerTaskWidget::onNewChildTaskActionTriggered()
{
    PrjTaskEditDialog editDialog(this);
    if (editDialog.exec())
    {
        QString uuid = QUuid::createUuid().toString(QUuid::WithoutBraces);
        QString taskName = editDialog.getTaskName();
        QString taskDescription = editDialog.getTaskDescription();
        QString currentTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        bool ret = insertNewTask(uuid,
                                 m_prjUuid,
                                 m_currentMenuAtItem->data(0, Qt::UserRole).toString(),
                                 taskName,
                                 taskDescription,
                                 currentTime,
                                 currentTime,
                                 0);

        if (!ret)
        {
            return ;
        }

        QTreeWidgetItem* newItem = new QTreeWidgetItem({taskName, taskDescription});
        newItem->setData(0, Qt::UserRole, uuid);
        m_currentMenuAtItem->addChild(newItem);
    }
}

void PrjManagerTaskWidget::onEditTaskActionTriggered()
{
    PrjTaskEditDialog editDialog(this);
    editDialog.setTaskName(m_currentMenuAtItem->text(0));
    editDialog.setTaskDescription(m_currentMenuAtItem->text(1));
    if (editDialog.exec())
    {
        QString uuid = m_currentMenuAtItem->data(0, Qt::UserRole).toString();
        QString parentUuid;
        QTreeWidgetItem* parentItem = m_currentMenuAtItem->parent();
        if (parentItem)
        {
            parentUuid = parentItem->data(0, Qt::UserRole).toString();
        }
        QString taskName = editDialog.getTaskName();
        QString taskDescription = editDialog.getTaskDescription();
        QString currentTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        bool ret = updateTask(uuid,
                              parentUuid,
                              taskName,
                              taskDescription,
                              currentTime,
                              0);

        if (!ret)
        {
            return ;
        }

        m_currentMenuAtItem->setText(0, taskName);
        m_currentMenuAtItem->setText(1, taskDescription);
    }
}

void PrjManagerTaskWidget::onDeleteTaskActionTriggered()
{
    int ret = deleteTask(m_currentMenuAtItem->data(0, Qt::UserRole).toString());
    if (!ret)
    {
        return ;
    }

    QTreeWidgetItem* parentItem = m_currentMenuAtItem->parent();
    if (parentItem)
    {
        parentItem->removeChild(m_currentMenuAtItem);
    }
    else
    {
        int index = -1;
        for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++)
        {
            if (ui->treeWidget->topLevelItem(i) == m_currentMenuAtItem)
            {
                index = i;
                break;
            }
        }

        if (index != -1)
        {
            delete ui->treeWidget->takeTopLevelItem(index);
        }
    }
}

void PrjManagerTaskWidget::onDeleteChildTaskActionTriggered()
{
    int ret = deleteChildTask(m_currentMenuAtItem->data(0, Qt::UserRole).toString());
    if (!ret)
    {
        return ;
    }

    for(int i = m_currentMenuAtItem->childCount() - 1; i >= 0; i--)
    {
        QTreeWidgetItem *childItem = m_currentMenuAtItem->child(i);//删除子节点
        deleteTreeWidgetItem(childItem);
        m_currentMenuAtItem->removeChild(childItem);
    }
}
